package com.gjy.test.netty.codec;

import com.gjy.netty.codec.StringProcessHandler;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.util.CharsetUtil;
import org.junit.jupiter.api.Test;

import java.util.concurrent.ThreadLocalRandom;

/**
 * @author 宫静雨
 * @version 1.0
 * @since 2023-01-10 14:43:06
 */
public class BuiltinDecoder {

    @Test
    public void FixedLengthFrameDecoder() {
        // 固定长度数据包解码器 —— FixedLengthFrameDecoder
        ChannelInitializer<EmbeddedChannel> channelInitializer = new ChannelInitializer<EmbeddedChannel>() {
            @Override
            protected void initChannel(EmbeddedChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast(new FixedLengthFrameDecoder(1024));
            }
        };
        EmbeddedChannel channel = new EmbeddedChannel(channelInitializer);
    }

    @Test
    public void LineBasedFrameDecoder() {
        // 行分割数据包解码器——LineBasedFrameDecoder
        String split = "\r\n";
        String content = "Hello World ";

        ChannelInitializer<EmbeddedChannel> channelInitializer = new ChannelInitializer<EmbeddedChannel>() {
            @Override
            protected void initChannel(EmbeddedChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast(new LineBasedFrameDecoder(1024));
                pipeline.addLast(new StringDecoder());
                pipeline.addLast(new StringProcessHandler());
            }
        };
        EmbeddedChannel channel = new EmbeddedChannel(channelInitializer);

        for (int i = 0; i < 10; i++) {
            int random = ThreadLocalRandom.current().nextInt(3) + 1;
            ByteBuf buffer = Unpooled.buffer();
            for (int j = 0; j < random; j++) {
                buffer.writeBytes(content.getBytes(CharsetUtil.UTF_8));
            }
            buffer.writeBytes(split.getBytes(CharsetUtil.UTF_8));
            channel.writeInbound(buffer);
        }
    }

    @Test
    public void DelimiterBasedFrameDecoder() {
        // 自定义分隔符数据包解码器——DelimiterBasedFrameDecoder
        String split = "\r\n";
        String content = "Hello World ";

        ChannelInitializer<EmbeddedChannel> channelInitializer = new ChannelInitializer<EmbeddedChannel>() {
            @Override
            protected void initChannel(EmbeddedChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast(new DelimiterBasedFrameDecoder(1024, true,
                        Unpooled.copiedBuffer(split.getBytes(CharsetUtil.UTF_8))));
                pipeline.addLast(new StringDecoder());
                pipeline.addLast(new StringProcessHandler());
            }
        };
        EmbeddedChannel channel = new EmbeddedChannel(channelInitializer);
        for (int i = 0; i < 10; i++) {
            int random = ThreadLocalRandom.current().nextInt(3) + 1;
            ByteBuf buffer = Unpooled.buffer();
            for (int j = 0; j < random; j++) {
                buffer.writeBytes(content.getBytes(CharsetUtil.UTF_8));
            }
            buffer.writeBytes(split.getBytes(CharsetUtil.UTF_8));
            channel.writeInbound(buffer);
        }
    }

    @Test
    public void LengthFieldBasedFrameDecoder() throws InterruptedException {
        // 自定义长度数据包解码器——LengthFieldBasedFrameDecoder
        String content = "Hello World ";

        final LengthFieldBasedFrameDecoder lengthFieldBasedFrameDecoder
                = new LengthFieldBasedFrameDecoder(1024, 0, 4,
                0, 4);
        ChannelInitializer<EmbeddedChannel> channelInitializer = new ChannelInitializer<EmbeddedChannel>() {
            @Override
            protected void initChannel(EmbeddedChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast(lengthFieldBasedFrameDecoder);
                pipeline.addLast(new StringDecoder());
                pipeline.addLast(new StringProcessHandler());
            }
        };
        EmbeddedChannel channel = new EmbeddedChannel(channelInitializer);
        for (int i = 0; i < 10; i++) {
            ByteBuf buffer = Unpooled.buffer();
            byte[] bytes = (i + " 次发送 -> " + content).getBytes(CharsetUtil.UTF_8);
            buffer.writeInt(bytes.length);
            buffer.writeBytes(bytes);
            channel.writeInbound(buffer);
        }
    }
}
